import 'dart:async';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_sound_elem.dart';
import 'package:video_ducafecat_flutter_v3/common/index.dart';
import 'package:tencent_cloud_chat_sdk/enum/conversation_type.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';

import 'index.dart';

class ChatController extends GetxController {
  ChatController({
    required this.receiver,
    required this.type,
  });

  // 刷新控制器
  final RefreshController refreshController = RefreshController();

  // 聊天页面滚动控制器
  final ScrollController scrollController = ScrollController();

  // 用户 uid
  final String receiver;

  // 聊天类型 1: 单聊 2: 群聊
  final int type;

  // 会话标题
  String title = '';

  // 会话
  V2TimConversation? conversation;
  // 分组信息
  V2TimGroupInfo? group;
  // 人员列表
  List<V2TimGroupMemberFullInfo?>? membersList;
  // 用户数据
  UserProfileModel user = UserProfileModel();
  // 消息列表
  List<V2TimMessage> messageList = [];
  // 语音消息列表
  Map<String, SoundMedia> mapSoundList = {};
  // 语音播放订阅
  StreamSubscription<Object>? subscriptionSoundPlay;

  // // 消息监听
  // late final IMMessageListener _messageListener;
  // // 群组监听
  // late final IMGroupListener _groupListener;
  // 聊天条数
  final int _limit = 20;
  // 是否还有更多
  bool _noMore = false;
  // 最后一条消息 id
  String? _lastMsgID;

  // 群信息编辑面板
  TextEditingController groupNameTextEditingController =
      TextEditingController();

  // global key 侧栏控制用
  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

  ////////////////////////////////////////////////////

  // 聊天输入栏 key
  GlobalKey<ChatBarWidgetState> chatBarKey = GlobalKey();

  // 聊天输入框控制器
  final TextEditingController chatTextEditingController =
      TextEditingController();

  // 是否是群聊
  bool get isGroup => type == ConversationType.V2TIM_GROUP;

  // 是否群主
  bool get isOwner => group?.owner == UserService.to.profile.username;

  // 是否 reverse 显示
  // bool get isReverse => messageList.length > 3;
  // bool get isReverse => scrollController.hasClients
  //     ? scrollController.position.pixels != 0
  //     : false;

  ////////////////////////////////////////////////////

  // 监听到新消息
  void onRecvNewMessage(V2TimMessage data) {
    if (data.userID != receiver && data.groupID != receiver) return;
    _addMessages([data]);
    _setMessageAsRead();
    update(['messageList']);
  }

  // 监听到更新消息
  void onRecvModifyMessage(V2TimMessage data) {
    if (data.userID != receiver && data.groupID != receiver) return;
    _modifyMessage(data);
    _setMessageAsRead();
    update(['messageList']);
  }

  //////////////////////////////////////////////////////

  // 初始数据
  _initData() async {
    final prefix = isGroup ? 'group_' : 'c2c_';
    try {
      conversation =
          await IMService.to.manager.getConversation(prefix + receiver);
      user.nickName = conversation?.showName ?? user.nickName;

      await _loadGroupInfo();

      title = isGroup ? group?.groupName ?? '' : user.nickName ?? '';
      update(['chat']);

      if ((conversation?.unreadCount ?? 0) > 0) _setMessageAsRead();
      if (messageList.isEmpty) _getMessageList();
    } catch (error) {
      // 显示错误信息
      try {
        String? showName =
            isGroup ? group?.groupName ?? '' : user.nickName ?? '';
        String? errDesc = error as String?;
        Loading.toast("$showName $errDesc");
      } catch (_) {}
      // 不强制删除会话
      // chatIndexPageConversationDeletedByCid(conversation!.conversationID);
      // Loading.toast(LocaleKeys.chatErrorInit.tr);
      Get.back();
    }
  }

  // 组信息
  Future<void> _loadGroupInfo() async {
    if (isGroup) {
      group = await IMService.to.manager.getGroup(receiver);
      V2TimGroupMemberInfoResult groupMember = await IMService.to.manager
          .getGroupMemberList(gid: receiver, nextSeq: "0");
      membersList = groupMember.memberInfoList;

      // 组名称
      groupNameTextEditingController.text = group?.groupName ?? '';
      // 界面标题
      title = group?.groupName ?? '';
    }
    update(['chat', 'group_setting_view']);
  }

  /////////////////////////////////////////////////////

  @override
  void onInit() {
    super.onInit();

    // 监听播放状态
    subscriptionSoundPlay =
        SoundPlayer.playStateListener(listener: (PlayerState state) {
      String? playerUri = SoundPlayer.sourceUri;
      for (String key in mapSoundList.keys) {
        var item = mapSoundList[key];
        if (item == null) {
          continue;
        }
        item.isPlaying = false;
        if (item.msgID == playerUri && state == PlayerState.playing) {
          item.isPlaying = true;
        }
        // else if (state == PlayerState.playing) {
        //   item.isPlaying = true;
        // } else if (state == PlayerState.completed ||
        //     state == PlayerState.stopped ||
        //     state == PlayerState.paused) {
        //   setState(() {
        //     isPlaying = false;
        //   });
        // }
      }
      update(['messageList']);
    });
  }

  @override
  void onReady() {
    super.onReady();
    _initData();
  }

  @override
  void onClose() {
    // IMService.to.removeMessageListener(_messageListener);
    // IMService.to.removeGroupListener(_groupListener);
    _setMessageAsRead();
    chatTextEditingController.dispose();
    groupNameTextEditingController.dispose();
    scrollController.dispose();
    refreshController.dispose();

    // 语音消息
    if (SoundPlayer.isInited && SoundPlayer.isPlaying) {
      SoundPlayer.stop();
    }
    subscriptionSoundPlay?.cancel();

    super.onClose();
  }

  ////////////////////////////////////////////////////

  // 添加消息
  void _addMessages(List<V2TimMessage> data, [bool isOld = false]) {
    // data 按 timestamp 时间戳 降序
    data.sort((left, right) {
      final rightTimestamp = right.timestamp ?? 0;
      final leftTimestamp = left.timestamp ?? 0;
      return rightTimestamp.compareTo(leftTimestamp);
    });

    if (data.isNotEmpty && isOld) _lastMsgID = data.last.msgID;
    for (var index = 0; index < data.length; index++) {
      final current = data[index];
      messageList.add(current);

      // 语音列表
      if (current.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND &&
          current.msgID != null) {
        mapSoundList[current.msgID!] = SoundMedia(msgID: current.msgID!);
      }
    }
  }

  // 获取消息列表
  Future<void> _getMessageList() async {
    final result = await IMService.to.manager.getMessageList(
      uid: !isGroup ? conversation?.userID : null,
      gid: isGroup ? conversation?.groupID : null,
      count: _limit,
      lastMsgID: _lastMsgID,
    );
    _addMessages(result, true);
    update(['messageList']);

    _noMore = result.length < _limit;
  }

  // 设置消息已读
  void _setMessageAsRead() async {
    await IMService.to.manager.setMessageAsRead(
      uid: !isGroup ? conversation?.userID : null,
      gid: isGroup ? conversation?.groupID : null,
    );
  }

  // 修改消息
  void _modifyMessage(V2TimMessage? message) {
    if (message?.id == null) {
      return;
    }

    // 消息列表
    final index = messageList.indexWhere((element) {
      return element.id == message?.id;
    });
    if (index < 0) return;
    messageList[index] = message!;

    // 语音列表
    if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND &&
        message.msgID != null) {
      mapSoundList[message.msgID!] = SoundMedia(msgID: message.msgID!);
    }

    update(['messageList']);
  }

  // 当前会话删除错误消息
  Future<void> _deleteMessages(String msgID) async {
    if (msgID.isEmpty) return;

    // 消息列表
    messageList.removeWhere((element) => element.id == msgID);

    // 语音列表
    mapSoundList.remove(msgID);

    update(["chat"]);
  }

  // 发送消息
  Future<void> _sendMessage(String id, V2TimMessage? message) async {
    if (message == null) return;
    scrollController.animateTo(
      0,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeIn,
    );
    message.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
    message.sender = UserService.to.username;
    _addMessages([message]);
    update(['messageList']);

    try {
      final receiver = isGroup ? conversation?.groupID : conversation?.userID;
      V2TimMessage result = await IMService.to.manager.sendMessage(
        id: id,
        uid: !isGroup ? receiver : null,
        gid: isGroup ? receiver : null,
      );
      _modifyMessage(result);
    } catch (error) {
      // 无效消息记录删除
      if (error is String) {
        _deleteMessages(id);
        return Loading.error(error);
      }

      // 发送失败状态
      if (error is! V2TimMessage) return;
      _modifyMessage(error);
    }
    update(['messageList']);
  }

  // 下载语音消息
  Future<void> _downloadSoundMessageDetail(V2TimMessage? message) async {
    String msgID = message?.msgID ?? '';
    V2TimSoundElem? soundElem = message?.soundElem;

    if (msgID.isNotEmpty) {
      if (soundElem?.url == null || soundElem?.url == '') {
        // 获取语音信息
        final response =
            await IMService.to.manager.getMessageOnlineUrl(msgID: msgID);
        if (response.data != null) {
          soundElem = response.data!.soundElem!;
          message?.soundElem = soundElem;
        }
      }

      // 下载语音文件
      if (soundElem?.localUrl == null || soundElem?.localUrl == '') {
        await IMService.to.manager.downloadMessage(
          msgID: msgID,
          messageType: 4,
          imageType: 0,
          isSnapshot: false,
        );
      }
    }
  }

  ////////////////////////////////////////////////////

  // 下拉刷新
  void onLoading() {
    if (!_noMore) {
      _getMessageList().then((_) {
        refreshController.loadComplete();
      }).catchError((_) {
        refreshController.loadFailed();
      });
    } else {
      refreshController.loadNoData();
    }
  }

  // 关闭聊天栏
  void onCloseChatBar() {
    chatBarKey.currentState?.onClose();
    update(["chat"]);
  }

  // 发送文字消息
  Future<void> onTextSend(String msg) async {
    final text = msg.trim();
    if (text.isEmpty) return;

    final result = await IMService.to.manager.createTextMessage(text);
    _sendMessage(result.id ?? '', result.messageInfo);
  }

  // 重新发送消息
  Future<void> onReSend(V2TimMessage msg) async {
    if (msg.msgID == null) return;

    // 重新发送
    final V2TimMessage result =
        await IMService.to.manager.reSendMessage(msgID: msg.msgID!);

    // 更新状态
    msg.status = result.status;

    // 更新消息列表
    _modifyMessage(msg);

    update(["messageList"]);
  }

  // 组信息打开
  void onGroupSettingOpen() {
    scaffoldKey.currentState?.openEndDrawer();
  }

  // 群信息根系
  Future<void> onRecvChatGroupInfoChanged() async {
    await _loadGroupInfo();
  }

  // 退出群聊
  // 群主不可以退群，只能 解散群组。
  Future<void> onQuitGroup() async {
    Get.back();
    await IMService.to.manager.quitGroup(receiver);
    Get.back();
  }

  // 解散群组
  Future<void> onDismissGroup() async {
    Get.back();
    await UserApi.chatDeleteGroup(UserService.to.username, receiver);
  }

  // 群踢人
  Future<void> onGroupMemberKick(String userID) async {
    ActionDialog.normal(
      context: Get.context!,
      title: Text(LocaleKeys.chatGroupSettingMemberKick.tr),
      content: Text(LocaleKeys.commonRemoveContent.trParams({"name": userID})),
      confirm: Text(LocaleKeys.commonBottomConfirm.tr),
      confirmBackgroundColor: Colors.red,
      onConfirm: () async {
        await IMService.to.manager
            .groupMemberKick(gid: receiver, memberIDs: [userID]);
      },
    );
  }

  // 加人
  Future<void> onGroupMemberAdd() async {
    var result = await Get.toNamed(RouteNames.chatChatFindUser);
    if (result == null || result.isEmpty) return;
    List<UserModel> selectedUsers = result as List<UserModel>;
    List<String> userIDs = selectedUsers.map((e) => e.nickName ?? "").toList();
    await IMService.to.manager.groupMemberInvite(
      gid: receiver,
      userIDs: userIDs,
    );
  }

  // 修改群名称
  Future<void> onGroupNameChanged(String groupName) async {
    // 群组形态包括 Public（公开群），
    // Private（即 Work，好友工作群），
    // ChatRoom（即 Meeting，会议群），
    // AVChatRoom（音视频聊天室），
    // BChatRoom（在线成员广播大群）和社群（Community）
    await IMService.to.manager.setGroup(V2TimGroupInfo(
      groupID: receiver,
      groupType: GroupType.Work,
      groupName: groupName,
    ));

    Get.back();
  }

  // 关闭聊天窗口
  void onChatClose() {
    Get.back();
  }

  // 发送表情消息
  Future<void> onFaceSend(int index, String data) async {
    final text = data.trim();
    if (text.isEmpty) return;

    final result = await IMService.to.manager.createFaceMessage(index, data);
    _sendMessage(result.id ?? '', result.messageInfo);
  }

  // 发送语音消息
  Future<void> onSoundSend(String path, int duration) async {
    if (path.isEmpty) return;

    final result =
        await IMService.to.manager.createSoundMessage(path, duration: duration);
    _sendMessage(result.id ?? '', result.messageInfo);
  }

  // 播放声音
  Future<void> onPlaySound(V2TimMessage message) async {
    // 下载语音消息
    await _downloadSoundMessageDetail(message);

    // 是否在播放
    bool isPlaying = mapSoundList[message.msgID]?.isPlaying ?? false;

    // 播放文件
    String? localUrl = message.soundElem?.localUrl;
    // 播放 url
    String? url = message.soundElem?.url;

    // 先初始化播放器
    if (!SoundPlayer.isInited) {
      SoundPlayer.initSoundPlayer();
    }
    // 播放控制
    if (isPlaying) {
      SoundPlayer.stop();
    } else {
      // 1 本地文件优选播放
      if (localUrl != null) {
        SoundPlayer.sourceUri = message.msgID;
        SoundPlayer.playLocal(localFile: localUrl);
      } else {
        // 2 网络文件播放
        if (url != null) {
          SoundPlayer.sourceUri = message.msgID;
          SoundPlayer.playUrl(url: url);
        }
      }
    }
  }

  // 是否在播放
  bool isPlaying(String? msgID) {
    return mapSoundList[msgID]?.isPlaying ?? false;
  }
}
